package com.soul.net.http;

import com.soul.enums.RequestProtocol;
import com.soul.exceptions.SoulRemoteException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * 请求httpClient构建类
 */
public class HttpClientBuilder {
    
    //等待响应超时时间
    private Integer socketTimeout;
    //获取请求超时时间
    private Integer connectionRequestTimeout;
    //建立连接超时时间
    private Integer connectTimeout;
    
    public HttpClientBuilder connectTimeout(Integer connectTimeout){
        this.connectTimeout = connectTimeout;
        return this;
    }

    public HttpClientBuilder socketTimeout(Integer socketTimeout){
        this.socketTimeout = socketTimeout;
        return this;
    }
    
    public HttpClientBuilder connectionRequestTimeout(Integer connectionRequestTimeout){
        this.connectionRequestTimeout = connectionRequestTimeout;
        return this;
    }

    public CloseableHttpClient build(){
        RequestConfig.Builder custom = RequestConfig.custom();
        if (socketTimeout != null){
            custom.setSocketTimeout(socketTimeout);
        }
        if (connectionRequestTimeout != null){
            custom.setConnectionRequestTimeout(connectionRequestTimeout);
        }
        if (connectTimeout != null){
            custom.setConnectTimeout(connectTimeout);
        }
        try {
            SSLContextBuilder builder = new SSLContextBuilder();
            // 全部信任 不做身份鉴定
            builder.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            });
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register(RequestProtocol.HTTP.toString(), new PlainConnectionSocketFactory())
                    .register(RequestProtocol.HTTPS.toString(), sslsf)
                    .build();
            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
            cm.setMaxTotal(200);
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .setConnectionManager(cm)
                    .setConnectionManagerShared(true)
                    .setDefaultRequestConfig(custom.build())
                    .build();
            return httpClient;
        }catch (SoulRemoteException e){
            throw e;
        }catch (Exception e){
            throw new SoulRemoteException(e);
        }
    }

}
